package org.platform.service.knowledge;

import com.alibaba.fastjson.JSON;
import com.mc.mic.core.log.bus.BusLogPusher;
import com.mc.mic.core.log.frame.LogBo;
import lombok.extern.slf4j.Slf4j;
import org.platform.constant.ApplyStatusConstant;
import org.platform.constant.DiagnoseTypeConstant;
import org.platform.constant.LogType;
import org.platform.dao.mapper.FdKbKnowledgemainMapper;
import org.platform.mo.bussmo.log.OperationMqBO;
import org.platform.mo.csmo.cmd10022.KnowApplyRequestParam;
import org.platform.mo.csmo.cmd10022.KnowApplyResponseParam;
import org.platform.mo.csmo.cmd10023.KnowAuditRequestParam;
import org.platform.mo.csmo.cmd10023.KnowAuditResponseParam;
import org.platform.mo.csmo.cmd10024.KnowPublishRequestParam;
import org.platform.mo.csmo.cmd10024.KnowPublishResponseParam;
import org.platform.mo.csmo.cmd10025.KnowledgeQueryRequestParam;
import org.platform.mo.csmo.cmd10025.KnowledgeQueryResponseParam;
import org.platform.mo.csmo.common.KB_Main;
import org.platform.mo.db.FdKbKnowledgemain;
import org.platform.processor.knowledge.KnowledgeApplyReceiveProcessor;
import org.platform.processor.knowledge.KnowledgeAuditReceiveProcessor;
import org.platform.processor.knowledge.KnowledgePublishReceiveProcessor;
import org.platform.service.IBaseService;
import org.platform.tool.helper.FileHelper;
import org.platform.tool.helper.LogHelper;
import org.platform.tool.util.BeansUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * 知识申请流程
 * 1. 知识申请分为三类:故障监测点(列表)/测试/故障树
 * 2. 知识申请将知识打包,KnowledgeMain/各自的知识的数据结构
 * 3. 更新知识主表(知识申请人/知识申请时间)
 * 4. 增加知识主表字段(状态(申请.审批通过,审批拒绝).版本号)
 * 5. 拷贝知识文件到指定目录;(记录操作日志)
 * 文件名: KnowApply_Station(Sanya/Miyun/Kashi)_KnowType(知识类型:故障监测点(列表)/测试/故障树)_时间戳
 * <p>
 * <p>
 * 知识审核流程
 * 1. 解析回来的数据结构,是否审批通过,更新数据库关联数据表
 * /FDRoot/KB/KnowAudit
 * <p>
 * 2. 审批不通过,更新知识主表(记录操作日志)
 * <p>
 * 3. 系统初始化的时候需要监听知识发布目录;
 * <p>
 * 内容:
 * <p>
 * 监测点:List
 * 测试:TestReposeParam/KnowledgeMain
 * 故障树:TreeMainResponseParam.KnowledgeMain
 * <p>
 * <p>
 * MonitorKnowApplyBean
 * TestKnowApplyBean
 * TreeKnowApplyBean
 * <p>
 * KnowApplyBean
 * Type
 * Context
 * <p>
 * <p>
 * 目录设计:(需要定义一个大的配置文件)
 * <p>
 * 监听目录:D:/FileRoot/FDRoot/KB/Temp
 * 发送目录:D:/FileRoot/CMCS_FD/Temp
 * <p>
 * <p>
 * <p>
 * <p>
 * 监听知识发布流程:
 * <p>
 * 1. 监听一个文件夹
 * 2. 将监听的知识入库,读取当前的组号,+1*
 * 3. 更新数据库
 * 4. 将文件归档(/FDRoot/KB/Apply)
 * <p>
 * 监测点:监测点组知识表.监测点知识表/知识主表
 * 测试:测试魔板表
 * 故障树:故障树/故障树节点/知识主表
 * <p>
 * <p>
 * 知识审批流程
 * <p>
 * 1. 修改知识主表,版本号增加0.1(如果审批通过)
 * 2. 知识的反向发布
 * <p>
 * <p>
 * 知识发布流程
 * <p>
 * 1. 按照用户选择的站点将文件放置到某个目录(存在多个拷贝)
 * 2. 文件名KnowledgePublish_Station_TimeInMills
 * 3. 本部有三个文件夹()
 * <p>
 * 知识审核通过(FileCommand)
 * <p>
 * 1. 删除申请知识(版本号为本部直接返回给你)(包括知识主表和子表)
 * 2. 入库(将本部的知识入库)
 * 3. 修改知识主表(将原有知识设置为不可用,新知识设置为可用)
 * 4. 操作日志
 * <p>
 * 知识审核不通过(FileCommand)
 * 1. 修改申请知识的知识主表(状态修改为审核不通过);
 * 2. 操作日志;
 * <p>
 * 获取当前的最高版本(公用方法)
 *
 * @author FengJie
 * @date 2018/4/10
 */

@Service
@Slf4j
public class KnowledgeServiceImpl implements IBaseService {
    @Autowired
    private KnowledgeApplyReceiveProcessor apply;
    @Autowired
    private KnowledgeAuditReceiveProcessor audit;
    @Autowired
    private KnowledgePublishReceiveProcessor publish;
    @Autowired
    private FdKbKnowledgemainMapper knowledgeMapper;
    @Autowired
    private BusLogPusher mqLog;
    @Autowired
    private FileHelper fileHelper;
    @Autowired
    private LogHelper logHelper;

    /**
     * 知识申请（10022）
     * <p>
     * 流程:
     * 1.找对应的知识模块
     * 2.更新ID已经 版本号
     * 3.本地入库
     * 4.创建成对应的文件
     */
    public KnowApplyResponseParam knowApply(KnowApplyRequestParam requestParam) throws IOException {
        try {
            logHelper.normal("正在执行创建知识申请流程", null, null);
            //初始化知识申请参数
            KnowApplyRequestParam applyParam = apply.getKnowledge(requestParam.getKbMain());
            requestParam.setKnowledgeCtx(applyParam.getKnowledgeCtx());
            apply.knowApplyInit(requestParam);
            requestParam.getKbMain().setStatus(ApplyStatusConstant.APPLY_PROCESSING);

            //1.本地数据库新建申请的内容  2.创建申请文件
            String applyData = JSON.toJSONString(requestParam);
            apply.addKnowledge(applyData);
            String knowledgeType = getKnowledgeType(requestParam.getKnowledgeType());
            fileHelper.createKnowledgeFile("KnowApply", requestParam.getStation(), applyData, knowledgeType);
            logHelper.normal("创建知识申请文件【成功】", null, null);
        } catch (RuntimeException r) {
            logHelper.error("创建知识申请文件【失败】", null, null, r);
        }
        return new KnowApplyResponseParam();
    }

    /**
     * 知识审核（10023）
     */
    public KnowAuditResponseParam knowAudit(KnowAuditRequestParam requestParam) throws IOException {
        try {
            KnowApplyRequestParam knowAuditRequestParam = new KnowApplyRequestParam();
            //封装审核参数
            KB_Main knowMain = requestParam.getKbMain();
            Boolean auditResult = requestParam.getAuditResult();
            knowMain.setAudittime(System.currentTimeMillis());
            knowMain.setStatus(auditResult ? ApplyStatusConstant.AUDIT_SUCCESS : ApplyStatusConstant.AUDIT_FAIL);
            knowAuditRequestParam.setKbMain(knowMain);

            //1.修改本地审核状态  2.创建审核文件
            String auditData = JSON.toJSONString(knowAuditRequestParam);
            audit.knowledgeAudit(auditData);
            String knowledgeType = getKnowledgeType(requestParam.getKbMain().getKnowledgetype());
            fileHelper.createKnowledgeFile("KnowAudit", knowMain.getStation(), auditData, knowledgeType);
            logHelper.normal("创建知识审核文件【成功】", null, null);
        } catch (RuntimeException r) {
            logHelper.error("创建知识审核文件【失败】", null, null, r);
        }
        return new KnowAuditResponseParam();
    }

    /**
     * 知识发布（10024）
     */
    public KnowPublishResponseParam knowPublish(KnowPublishRequestParam requestParam) {
        mqLog.log(new LogBo<>(LogType.OPERATION_LOG, new OperationMqBO("正在执行知识发布流程")));
        try {
            //查询对应发布的知识
            KnowApplyRequestParam publishParam = publish.getKnowledge(requestParam.getKbMain());
            publishParam.setKnowledgeType(requestParam.getKnowledgeType());
            publishParam.setKbMain(requestParam.getKbMain());
            publishParam.setKnowledgeID(requestParam.getKnowledgeID());
            publish.knowPublishInit(publishParam);

            //发送 发布的内容到指定的站点
            String publishData = JSON.toJSONString(publishParam);
            String knowledgeType = getKnowledgeType(publishParam.getKnowledgeType());
            Arrays.stream(requestParam.getStation()).forEach(s -> {

                //todo 联合调试的时候  这里日志需要重新修改
                try {
                    boolean status = fileHelper.createKnowledgeFile("KnowPublish", s, publishData, knowledgeType);
                    if (status) {
                        log.info("站点: " + s + " 知识发布【成功】");
                    } else {
                        log.info("站点: " + s + " 知识发布【失败】");
                    }
                } catch (IOException e) {
                    log.info("知识发布异常:" + e);
                }
            });
            logHelper.normal("知识发布【成功】", null, null);
        } catch (RuntimeException r) {
            logHelper.error("知识发布【失败】", null, null, r);
        }
        return new KnowPublishResponseParam();
    }

    /**
     * 查询所有的知识(10025)
     *
     * @param requestParam
     * @return
     */
    public KnowledgeQueryResponseParam queryKnowledge(KnowledgeQueryRequestParam requestParam) {
        KnowledgeQueryResponseParam responseParam = new KnowledgeQueryResponseParam();
        Example example = new Example(FdKbKnowledgemain.class);
        Example.Criteria criteria = example.createCriteria()
                .andEqualTo("station", requestParam.getStation())
                .andEqualTo("knowledgetype", requestParam.getTestType());
        if (null != requestParam.getUserBy()) {
            criteria.andEqualTo("userby", requestParam.getUserBy());
        }
        List<FdKbKnowledgemain> knowledgeList = knowledgeMapper.selectByExample(example);
        List<KB_Main> mainList = BeansUtils.copyListProperties(knowledgeList, KB_Main.class);
        responseParam.setKnowledgeList(mainList);
        return responseParam;
    }

    /**
     * 获取字符知识类型
     *
     * @param knowledgeType
     * @return
     */
    private String getKnowledgeType(int knowledgeType) {
        String strKnowledgeType;
        switch (knowledgeType) {
            case DiagnoseTypeConstant.KNOW_MONITOR:
                strKnowledgeType = DiagnoseTypeConstant.STR_KNOW_MONITOR;
                break;
            case DiagnoseTypeConstant.KNOW_TEST:
                strKnowledgeType = DiagnoseTypeConstant.STR_KNOW_TEST;
                break;
            case DiagnoseTypeConstant.KNOW_TREE:
                strKnowledgeType = DiagnoseTypeConstant.STR_KNOW_TREE;
                break;
            default:
                strKnowledgeType = "";
        }
        return strKnowledgeType;
    }

}
